#include "StdAfx.h"
#include "LayoutData.h"
#include "FileReader.h"
#include "FileWriter.h"
#include "Settings.h"
#include "TabListItem.h"

bool CLayoutInfo::Load(CBaseReader& r)
{
  CString val;

  if (!r.ReadPair(LAYOUT_INFO_INIFILE, iniFile))
    return false;

  if (!r.ReadPair(LAYOUT_INFO_APPEXECUTABLE, appExecutable))
    return false;

  if (!r.ReadPair(LAYOUT_INFO_APPWNDTITLE, appWndTitle))
    return false;

  if (!r.ReadPair(LAYOUT_INFO_APPWNDCLASS, appWndClass))
    return false;

  if (!r.ReadPair(LAYOUT_INFO_APPRESTART, val))
    return false;
  appRestart = (val.CompareNoCase(TEXT("yes")) == 0 || val.CompareNoCase(TEXT("y")) == 0);

  return true;
}

CLayoutData::CLayoutData(void)
  : m_iniFileUtf8(false)
{
}

CLayoutData::~CLayoutData(void)
{
  Clear();
}

bool CLayoutData::Load(const TCHAR* szLayoutFile)
{
  CFileReader fr;
  if (!fr.Open(szLayoutFile))
    return false;

  if (!LoadLayout(fr))
    return false;

  CFileReader inir;
  CString sIniFile;
  if (!m_layoutInfo.iniFile.IsEmpty() && m_layoutInfo.iniFile[0] != TEXT('\\'))
    sIniFile = CSettings::GetAppFolder();
  sIniFile += m_layoutInfo.iniFile;
  if (!inir.Open(sIniFile))
    return false;

  m_iniFileUtf8 = inir.IsUtf8();

  if (!LoadIni(inir))
    return false;

  if (!IniToLayout())
    return false;

  return true;
}

bool CLayoutData::Save()
{
  if (m_layoutInfo.iniFile.IsEmpty())
    return false;

  CFileWriter w;
  CString sIniFile = CSettings::GetAppFolder();
  sIniFile += m_layoutInfo.iniFile;
  if (!w.Open(sIniFile, m_iniFileUtf8))
    return false;

  if (!LayoutToIni())
    return false;

  return m_iniData.Save(w);
}

void CLayoutData::Clear()
{
  m_iniData.Clear();
  m_layoutInfo.Clear();

  for (CLayoutVector::iterator iter = m_layouts.begin(); iter != m_layouts.end(); iter++)
  {
    SLayout* pl = *iter;
    if (pl)
      delete pl;
  }
  m_layouts.clear();
}

int CLayoutData::GetTabIndex(const CString& name) const
{
  for (int i = 0; i < (int)m_layouts.size(); i++)
  {
    if (m_layouts[i]->tab.Compare(name) == 0)
      return i;
  }
  return -1;
}

CString CLayoutData::GetTabName(CLayoutList* pList) const
{
  for (CLayoutVector::const_iterator iter = m_layouts.begin(); iter != m_layouts.end(); iter++)
  {
    if (&(*iter)->list == pList)
      return (*iter)->tab;
  }
  return TEXT("");
}

bool CLayoutData::BuildTabList(CList& list)
{
  list.Clear();

  for (CLayoutVector::iterator iter = m_layouts.begin(); iter != m_layouts.end(); iter++)
  {
    CTabListItem* pItem = new CTabListItem((*iter)->tab, (*iter)->tab);
    if (pItem)
      list.Add(pItem);
  }

  return true;
}

CLayoutList* CLayoutData::GetLayout(int tabIdx)
{
  if (tabIdx >= 0 && tabIdx < (int)m_layouts.size())
    return &m_layouts[tabIdx]->list;

  return NULL;
}

bool CLayoutData::IsChanged()
{
  for (CLayoutVector::iterator iter = m_layouts.begin(); iter != m_layouts.end(); iter++)
  {
    SLayout* pLayout = *iter;
    if (!pLayout)
      continue;

    for (int i = 0; i < pLayout->list.GetCount(); i++)
    {
      CLayoutListItem* pItem = (CLayoutListItem*)pLayout->list.GetAt(i);
      if (pItem != NULL)
      {
        CIniItem* pIniItem = m_iniData.FindItem(pItem->GetName());
        if (pIniItem != NULL)
        {
          if (pItem->GetValue().Compare(pIniItem->GetValue()) != 0)
          {
            return true;
          }
        }
      }
    }
  }

  return false;
}

bool CLayoutData::LoadLayout(CBaseReader& r)
{
  if (!m_layoutInfo.Load(r))
    return false;

  // Read items
  CString type, name, tab;
  while (r.ReadPair(LAYOUT_ITEM_TYPE, type))
  {
    if (!r.ReadPair(LAYOUT_ITEM_NAME, name))
      return false;

    if (!r.ReadPair(LAYOUT_ITEM_TAB, tab))
      return false;

    CList* pList = GetLayoutList(tab);
    if (pList)
    {
      CLayoutListItem* pItem = CreateLayoutItem(type, name, tab);
      if (pItem)
      {
        bool res = pItem->Load(r);
        if (!res)
          Logger::LogFmt(lsWarning, TEXT("Failed to load item %s (line %d)"), name.GetString(), r.GetLine());

        pList->Add(pItem);
      }
      else
        Logger::LogFmt(lsWarning, TEXT("Failed to create item %s: not enough memory"), name.GetString());
    }
    else
      Logger::LogFmt(lsWarning, TEXT("Failed to create tab %s"), tab.GetString());
  }

  return m_layouts.size() > 0;
}

bool CLayoutData::LoadIni(CBaseReader& r)
{
  return m_iniData.Load(r);
}

bool CLayoutData::LayoutToIni()
{
  bool res = false;

  for (CLayoutVector::iterator iter = m_layouts.begin(); iter != m_layouts.end(); iter++)
  {
    SLayout* pLayout = *iter;
    if (!pLayout)
      continue;

    for (int i = 0; i < pLayout->list.GetCount(); i++)
    {
      CLayoutListItem* pItem = (CLayoutListItem*)pLayout->list.GetAt(i);
      if (pItem != NULL)
      {
        CIniItem* pIniItem = m_iniData.FindItem(pItem->GetName());
        if (pIniItem != NULL)
        {
          pIniItem->SetValue(pItem->GetValue());
          res = true;
        }
      }
    }
  }

  return res;
}

bool CLayoutData::IniToLayout()
{
  bool res = false;

  for (CLayoutVector::iterator iter = m_layouts.begin(); iter != m_layouts.end(); iter++)
  {
    SLayout* pLayout = *iter;
    if (!pLayout)
      continue;

    for (int i = 0; i < pLayout->list.GetCount(); i++)
    {
      CLayoutListItem* pItem = (CLayoutListItem*)pLayout->list.GetAt(i);
      if (pItem != NULL)
      {
        CIniItem* pIniItem = m_iniData.FindItem(pItem->GetName());
        if (pIniItem != NULL)
        {
          pItem->SetValue(pIniItem->GetValue());
          res = true;
        }
      }
    }
  }

  return res;
}

CLayoutListItem* CLayoutData::CreateLayoutItem(const CString& type, const CString& name, const CString& tab)
{
  if (type.CompareNoCase(LAYOUT_ITEM_TYPE_TEXT) == 0)
    return new CLayoutListItemText(name, tab);
  else if (type.CompareNoCase(LAYOUT_ITEM_TYPE_INT) == 0)
    return new CLayoutListItemInt(name, tab);
  else if (type.CompareNoCase(LAYOUT_ITEM_TYPE_CHECK) == 0)
    return new CLayoutListItemCheck(name, tab);
  else if (type.CompareNoCase(LAYOUT_ITEM_TYPE_STRLIST) == 0)
    return new CLayoutListItemStrList(name, tab);
  else if (type.CompareNoCase(LAYOUT_ITEM_TYPE_INTLIST) == 0)
    return new CLayoutListItemIntList(name, tab);
  else if (type.CompareNoCase(LAYOUT_ITEM_TYPE_FILELIST) == 0)
    return new CLayoutListItemFileList(name, tab);
  else if (type.CompareNoCase(LAYOUT_ITEM_TYPE_FILE) == 0)
    return new CLayoutListItemFile(name, tab);
  else if (type.CompareNoCase(LAYOUT_ITEM_TYPE_FOLDER) == 0)
    return new CLayoutListItemFolder(name, tab);
  else if (type.CompareNoCase(LAYOUT_ITEM_TYPE_EMAILACC) == 0)
    return new CLayoutListItemEmailAcc(name, tab);
  else if (type.CompareNoCase(LAYOUT_ITEM_TYPE_COLOR) == 0)
    return new CLayoutListItemColor(name, tab);
  else
    return NULL;
}

CLayoutList* CLayoutData::GetLayoutList(const CString& tab)
{
  for (CLayoutVector::iterator iter = m_layouts.begin(); iter != m_layouts.end(); iter++)
  {
    if ((*iter)->tab.CompareNoCase(tab) == 0)
      return &(*iter)->list;
  }
  SLayout* l = new SLayout();
  if (l)
  {
    l->tab = tab;
    m_layouts.push_back(l);
    return &l->list;
  }
  return NULL;
}